#!/usr/bin/env python2
import os
import sys
import errno
import uuid
import getopt
import subprocess
import time
import re
import ConfigParser
import fcntl

path = os.path.abspath(os.path.split(os.path.realpath(__file__))[0])
sys.path.insert(0, "%s/../admin/" %(path))

from buddha import lsb
from utils import Exp, _dwarn, _exec_pipe, _put_remote, _exec_system, _exec_shell, _derror, \
                _isip, _exec_remote, _exec_pipe1
from remotecopy_config import Config
from rpyc_srv import RpycSrv
from remotecopy_srv import RemoteCopySrv

REMOTE_COPY_INTERVAL_DEFAULT = 60
REMOTE_COPY_THREAD_DEFAULT = 10
REMOTE_COPY_QOS_DEFAULT = 10
REMOTE_COPY_CACHE_DEFAULT = 1024
BIN_PATH = '/usr/bin/'

def usage():
    print ("usage:")
    print (sys.argv[0] + " --start [client|server]")
    print (sys.argv[0] + " --stop [client|server]")
    print (sys.argv[0] + " --stat [client|server]")
    print ""
    print (sys.argv[0] + " --install")
    print (sys.argv[0] + " --update <xxx.tar.gz>")
    print (sys.argv[0] + " [--version -v] [--help -h]")

def get_version():
    res = _exec_pipe(["%s/get_version" % path], 0, False)
    print res,

class RemoteCopy():
    def __init__(self, ins):
        self.config = Config()
        path = os.path.abspath(os.path.split(os.path.realpath(__file__))[0])
        if os.path.dirname(path) != self.config.root_path and not ins:
            raise Exp(errno.EPERM, "please install remotecopy with remotecopy.py --install")

    def start(self, ext, foreground):
        conf = self.config.get_conf(ext)

        lfile = "/var/run/fusionstack_remotecopy_foreground_%s.lock" % ext
        lock_fd = open(lfile, 'a')
        try:
            fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
        except:
            _derror("service %s already running" %(ext))
            return

        if ext == 'server':
            rpc_srv = RpycSrv(conf[ext], self.config.home, foreground)
            rpc_srv.listen()
        else:
            rc_srv = RemoteCopySrv(self.config, conf, foreground)
            if (foreground):
                rc_srv.run()
            else:
                rc_srv.start()

    def stop(self, ext):
        conf = self.config.get_conf(ext)

        if ext == 'server':
            rpc_srv = RpycSrv(conf[ext], self.config.home)
            rpc_srv.stop()
        else:
            rc_srv = RemoteCopySrv(self.config, conf)
            rc_srv.stop()

    def stat(self, ext):
        conf = self.config.get_conf(ext)

        foreground = False
        lfile = "/var/run/fusionstack_remotecopy_foreground_%s.lock" % ext
        lock_fd = open(lfile, 'a')
        try:
            fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
        except IOError as err:
            if err.errno == errno.EAGAIN:
                foreground = True

        if ext == 'server':
            rpc_srv = RpycSrv(conf[ext], self.config.home, foreground)
            rpc_srv.stat(foreground)
        else:
            rc_srv = RemoteCopySrv(self.config, conf, foreground)
            rc_srv.stat(foreground)

    def update(self, ext):
        if not ext.endswith('.tar.gz'):
            raise Exp(errno.EINVAL, "%s is not xxx.tar.gz" % ext)
        if not os.path.exists(ext):
            raise Exp(errno.EINVAL, "%s not exists" % ext)

        tar = os.path.abspath(ext)
        res = _exec_pipe(['tar', 'tf', tar], 0, False)
        if res.split()[0] != 'remotecopy/':
            raise Exp(errno.EINVAL, "%s is not remotecopy package" % ext)

        res = _exec_pipe(['tar', 'xzvf', tar, "-C", os.path.dirname(os.path.dirname(path))], 0, False)

    def __install_init(self, home):
        (distro, release, codename) = lsb.lsb_release()
        if (distro == 'Ubuntu'):
            src = os.path.join(home, "src/lichrcd_init_ubuntu")
            dst = "/etc/init.d/lichrcd"
            cmd = 'cp %s %s' % (src, dst)
            os.system(cmd)

            ldst = "/etc/rcS.d/S42lichrcd"
            cmd = 'ln -s %s %s' % (dst, ldst)
            if not os.path.exists(ldst):
                os.system(cmd)
        elif (distro == 'CentOS'):
            version = int(release.split(".")[0])
            if version <=  6:
                src = os.path.join(home, "src/lichrcd_init_centos")
                dst = "/etc/init.d/lichrcd"
                cmd = 'cp %s %s' % (src, dst)
                os.system(cmd)
                os.system("chkconfig --add lichrcd")
            elif version == 7:
                src = os.path.join(home, "src/lichrcd.service")
                dst = "/usr/lib/systemd/system/lichrcd.service"
                cmd = 'cp %s %s' % (src, dst)
                os.system(cmd)
                cmd = "chmod 754 %s" % (dst)
                os.system(cmd)
                cmd = "systemctl enable lichrcd.service"
                os.system(cmd)
            else:
                raise Exception("not support %s %s %s" % (distro, release, codename))
        else:
            _derror("not support %s %s %s" % (distro, release, codename))
            pass

    def install(self):
        root_path = self.config.root_path
        if not os.path.exists(root_path):
            os.makedirs(root_path)

        if self.config.home == root_path:
            raise Exp(errno.EPERM, "already installed")

        bin_path = os.path.join(BIN_PATH, self.config.bin_name)
        res = _exec_pipe(['cp', '-r', self.config.home + '/admin', root_path], 0, True)
        res = _exec_pipe(['cp', '-r', self.config.home + '/src', root_path], 0, True)
        res = _exec_pipe(['cp', '-r', self.config.home + '/etc', root_path], 0, True)
        res = _exec_pipe(["rm", "-rf", bin_path], 0, True)
        res = _exec_pipe(["ln", '-s', root_path + "/src/remotecopy.py", bin_path], 0, True)

        self.__install_init(root_path)

def main():
    op = ""
    version = False
    foreground = False
    ext = None
    ins = False

    try:
        opts, args = getopt.getopt(
                sys.argv[1:],
                'hvfr', ['help', 'version', 'start=', 'stop=', 'stat=',
                    'update=', 'install']
                )
    except getopt.GetoptError, err:
        print str(err)
        usage()
        exit(errno.EINVAL)

    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            exit(0)
        elif o in ('-v', '--version'):
            get_version()
            exit(0)
        elif o in '-f':
            foreground = True
        elif o in '--start':
            op = o
            ext = a
            if ext not in ['server', 'client']:
                usage()
                exit(errno.EINVAL)
        elif o in '--stop':
            op = o
            ext = a
            if ext not in ['server', 'client']:
                usage()
                exit(errno.EINVAL)
        elif o in '--stat':
            op = o
            ext = a
            if ext not in ['server', 'client']:
                usage()
                exit(errno.EINVAL)
        elif o in '--update':
            op = o
            ext = a
        elif o in '--install':
            op = o
            ins = True
        else:
            usage()
            exit(errno.EINVAL)

    try:
        rc = RemoteCopy(ins)
    except Exp, e:
        _derror(e.err)
        exit(e.errno)

    if (op == "--start"):
        try:
            rc.start(ext, foreground)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--stop"):
        try:
            rc.stop(ext)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--stat"):
        try:
            rc.stat(ext)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--update"):
        try:
            rc.update(ext)
        except Exp, e:
            _derror(e.err)
            exit(e.errno)
    elif (op == "--install"):
        try:
            rc.install()
        except Exp, e:
            _derror(e.err)
            exit(e.errno)

if __name__ == '__main__':
    if (len(sys.argv) == 1):
        usage()
    else:
        main()
